package cn.wizzer.app.web.modules.controllers.platform.bus.equipment;

import cn.wizzer.app.bus.modules.models.BusinessFileInfo;
import cn.wizzer.app.bus.modules.models.InspectionItem;
import cn.wizzer.app.bus.modules.models.YJbxx;
import cn.wizzer.app.bus.modules.models.equipment.*;
import cn.wizzer.app.bus.modules.services.*;
import cn.wizzer.app.sys.modules.models.Sys_role;
import cn.wizzer.app.sys.modules.models.Sys_user;
import cn.wizzer.app.sys.modules.services.SysDictService;
import cn.wizzer.app.sys.modules.services.SysRoleService;
import cn.wizzer.app.sys.modules.services.SysUnitService;
import cn.wizzer.app.sys.modules.services.SysUserService;
import cn.wizzer.app.web.commons.base.Globals;
import cn.wizzer.app.web.commons.doc.DocUtils;
import cn.wizzer.app.web.commons.slog.annotation.SLog;
import cn.wizzer.app.web.commons.utils.DateUtil;
import cn.wizzer.app.web.commons.utils.ShiroUtil;
import cn.wizzer.app.web.commons.utils.StringUtil;
import cn.wizzer.app.web.modules.controllers.open.file.UploadController;
import cn.wizzer.framework.base.Result;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.*;

import javax.servlet.http.HttpServletRequest;

import org.nutz.trans.Atom;
import org.nutz.trans.Trans;

import java.io.File;
import java.sql.Connection;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tcjinxiu.com
 * @time 2024-04-11 10:19:44
 *
 */
@IocBean
@At("/platform/bus/equipment/report")
public class BusEquipmentReportController {
private static final Log log = Logs.get();
	@Inject
	BusEquipmentReportService busEquipmentReportService;
	@Inject
	BusEquipmentReportItemService busEquipmentReportItemService;
	@Inject
	BusEquipmentInspectionService busEquipmentInspectionService;
	@Inject
	BusEquipmentService busEquipmentService;
	@Inject
	BusEquipmentProcessService busEquipmentProcessService;
	@Inject
	private SysDictService sysDictService;
	@Inject
	private SysUnitService sysUnitService;
	@Inject
	private SysUserService sysUserService;
	@Inject
	private ShiroUtil shiroUtil;
	@Inject
	private BusinessFileInfoService businessFileInfoService;

	@Inject
	SysRoleService sysRoleService;
	private static final String type="report";

	//public static final int[] EquipmentReport = {0,1,2,3,4};//设备量值溯源(检定/校准)报告流程" ask department chargeLeader finance leadership
	@At("/?")
	@Ok("beetl:/platform/bus/equipment/report/index.html")
	@RequiresAuthentication
	public void index(String processName,HttpServletRequest req) {
		//String processCode = sysDictService.getProcessCode(processName);
		req.setAttribute("userId",StringUtil.getPlatformUid());
		req.setAttribute("processName", processName);
		Map processMap =sysDictService.getCodeMap("equipmentProcessCode");
		req.setAttribute("processMap", JSONObject.fromObject(processMap));
		req.setAttribute("processOptions", JSONArray.fromObject(busEquipmentProcessService.listThisProcess(processMap, new int[]{0, 1, 2, 3, 4})));
		req.setAttribute("calculateMap", JSONObject.fromObject(sysDictService.getCodeMap("calculate")));
		req.setAttribute("calculateOptions", JSONArray.fromObject(sysDictService.dictCodeTree("calculate")));
		req.setAttribute("calculateCycleTypeMap", JSONObject.fromObject(sysDictService.getCodeMap("calculateCycleType")));
		req.setAttribute("abilityMap", JSONObject.fromObject(sysDictService.getCodeMap("ability")));
		req.setAttribute("abilityOptions", JSONArray.fromObject(sysDictService.dictCodeTree("ability")));
		req.setAttribute("accordMap", JSONObject.fromObject(sysDictService.getCodeMap("accord")));
		req.setAttribute("accordOptions", JSONArray.fromObject(sysDictService.dictCodeTree("accord")));
		String sysadminRoleid = sysRoleService.fetch(Cnd.where("code", "=", "sysadmin")).getId();
		List<Sys_role> roles = StringUtil.getPlatformUser().getRoles();
		String role = roles.stream().map(t->t.getId()).collect(Collectors.joining(","));
		if (role.indexOf(sysadminRoleid)!=-1) {
			req.setAttribute("isAdmin", true);
		}else{
			req.setAttribute("isAdmin", false);
		}
	}

	@At
	@Ok("json:full")
	@RequiresAuthentication
	public Object data(@Param("code") String code, @Param("name") String name,@Param("lczt") String lczt,
					   @Param("processName") String processName,
					   @Param("pageNumber") int pageNumber,@Param("pageSize") int pageSize
			, @Param("pageOrderName") String pageOrderName, @Param("pageOrderBy") String pageOrderBy) {
		try {
			String sql = "select e.code,e.name,e.model,e.company,e.purchaseDate,e.purchasePrice," +
					" ur.username as managerName,ut.name as applyName,urr.username as opName, " +
					" es.id,es.lczt,es.nextspr,es.calculate,es.explains,es.reportCode,es.accord,es.conclusion,FROM_UNIXTIME(es.opAt) as opTime,es.opBy " +
					" from bus_equipment_report es  " +
					" left join bus_equipment e on es.equipmentId=e.id " +
					" left join sys_user ur on ur.id=e.managerBy " +
					" left join sys_unit ut on ut.id = e.applyDept " +
					" left join sys_user urr on urr.id=es.opBy " +
					" where es.delFlag=0 ";
			if(StringUtils.isNotBlank(processName)&& processName.equals("audit")){
				sql+= " and es.nextsprIds='"+StringUtil.getPlatformUid()+"' and (es.lczt = 2 or es.lczt = 1)";
			}else{
				//数据权限
				sql+= StringUtil.dataScopeFilter("es");
			}
			if(StringUtils.isNotBlank(code)){
				sql+= " and  e.code like '%"+code+"%' ";
			}
			if(StringUtils.isNotBlank(name)){
				sql+= " and  e.name like '%"+name+"%' ";
			}
			if(StringUtils.isNotBlank(lczt)){
				sql+= " and  es.lczt = '"+lczt+"' ";
			}
			sql="select * from ("+sql+") a";
			if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
				if ("ascending".equalsIgnoreCase(pageOrderBy)) {
					sql+= " order by "+pageOrderName+" asc,opTime desc ";
				} else {
					sql+= " order by "+pageOrderName+" desc,opTime desc ";
				}
			}else{
				sql+= " order by opTime desc ";
			}
			return Result.success().addData(busEquipmentReportService.listPage(pageNumber, pageSize, Sqls.create(sql)));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return Result.error();
		}
	}

	@Aop(TransAop.READ_COMMITTED)
	@At
	@Ok("json")
	@RequiresPermissions("equipment.report.add")
	@SLog(tag = "Add", msg = "Add:bus_equipment_report")
	public Object addDo(@Param("report") BusEquipmentReport report, HttpServletRequest req) {
		try {
			for(int i =0 ;i<report.getReportItems().size();i++){
				report.getReportItems().get(i).setSort(i);
			}
			report = busEquipmentReportService.insertWith(report,"reportItems");
			BusEquipmentProcess process = new BusEquipmentProcess();
			process.setHeadId(report.getId());
			process.setEquipmentId(report.getEquipmentId());
			process.setLczt(report.getLczt());
			process.setType(type);
			process.setStatus("0");
			process.setNextspr(report.getNextspr());
			process.setNextsprIds(report.getNextsprIds());
			busEquipmentProcessService.insert(process);
			busEquipmentReportService.clearCache();
			return Result.success("system.success");
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}

	@At("/detail/?")
	@Ok("json")
	@RequiresAuthentication
	public Object detail(String id) {
		BusEquipmentReport report = busEquipmentReportService.fetchLinks(busEquipmentReportService.fetch(id),"reportItems",Cnd.NEW().asc("sort"));
		NutMap map = new NutMap();
		if(StringUtils.isNotBlank(report.getInspectionId())) {
			BusEquipmentInspection inspection = busEquipmentInspectionService.fetch(report.getInspectionId());
			map.addv("inspection", inspection);
		}
		List listProcess = busEquipmentProcessService.list(Sqls.create("select *,(select username from sys_user where id = es.opBy) as opName,FROM_UNIXTIME(es.opAt) as opTime from  bus_equipment_process es where " +
				" equipmentId='"+report.getEquipmentId()+"' and headId='"+report.getId()+"' and type='"+type+"' order by opAt desc"));
		map.addv("report", report);
		map.addv("listProcess", listProcess);
		try {
			return Result.success("system.success").addData(map);
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}

	@Aop(TransAop.READ_COMMITTED)
	@At
	@Ok("json")
	@RequiresPermissions("equipment.report.edit")
	@SLog(tag = "Edit", msg = "Edit:bus_equipment_report")
	public Object editDo(@Param("report") BusEquipmentReport report, HttpServletRequest req) {
		try {
			BusEquipmentProcess process = new BusEquipmentProcess();
			process.setHeadId(report.getId());
			process.setEquipmentId(report.getEquipmentId());
			process.setLczt(report.getLczt());
			process.setType(type);
			process.setStatus("0");
			process.setOpBy(StringUtil.getPlatformUid());
			process.setOpAt(Times.getTS());
			process.setNextspr(report.getNextspr());
			process.setNextsprIds(report.getNextsprIds());
			//busEquipmentService.update(equipment);
			busEquipmentReportService.update(report);
			List<BusEquipmentReportItem> reportItems = report.getReportItems();
			int i =0;
			for (BusEquipmentReportItem item : reportItems) {
				item.setOpBy(StringUtil.getPlatformUid());
				item.setOpAt(Times.getTS());
				item.setReportId(report.getId());
				item.setSort(i);
				this.busEquipmentReportItemService.insertOrUpdate(item);
				i++;
			}
			busEquipmentProcessService.execute(Sqls.create("update bus_equipment_process set delflag=1 where lczt>=" + report.getLczt() + " and headId='" + report.getId() + "' and type='" + type + "' "));
			busEquipmentProcessService.insert(process);
			busEquipmentReportService.clearCache();
			return Result.success("system.success");
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}

	@Aop(TransAop.READ_COMMITTED)
	@At("/subDo/?")
	@Ok("json")
	@RequiresPermissions("equipment.report.edit")
	@SLog(tag = "subDo", msg = "subDo:bus_equipment_report")
	public Object subDo(String id) {
		try {
			BusEquipmentReport report = busEquipmentReportService.fetch(id);
			report.setLczt("1");
			BusEquipmentProcess process = busEquipmentProcessService.fetch(Cnd.NEW().and("headId", "=", report.getId())
					.and("lczt","=","0").and("delflag","=","0").and("type", "=", type));
			process.setHeadId(report.getId());
			process.setEquipmentId(report.getEquipmentId());
			process.setLczt(report.getLczt());
			process.setType(type);
			process.setStatus("0");
			process.setOpBy(StringUtil.getPlatformUid());
			process.setOpAt(Times.getTS());
			busEquipmentReportService.update(report);
			busEquipmentProcessService.execute(Sqls.create("update bus_equipment_process set delflag=1 where lczt>=" + report.getLczt() + " and headId='" + report.getId() + "' and type='" + type + "' "));
			busEquipmentProcessService.insert(process);
			busEquipmentReportService.clearCache();
			return Result.success("system.success");
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}

	@Aop(TransAop.READ_COMMITTED)
	@At
	@Ok("json")
	@RequiresAuthentication
	@SLog(tag = "processDo", msg = "processDo:bus_equipment_report")
	public Object processDo(@Param("..") BusEquipmentReport report,@Param("..") BusEquipmentProcess process,
							HttpServletRequest req) {
		try {
			BusEquipment equipment = busEquipmentService.fetch(report.getEquipmentId());
			if (report.getAuditFlag().equals("0")) {
				report.setLczt("2");
			} else if (process.getStatus().equals("0")) {
				report.setLczt("4");
				report.setNextspr(null);
				report.setNextsprIds(null);
				process.setNextspr(null);
				process.setNextsprIds(null);
				equipment.setReportCode(report.getReportCode());
				equipment.setCalculate(report.getCalculate());
			} else {
				report.setLczt("3");
				report.setNextspr(null);
				report.setNextsprIds(null);
				process.setNextspr(null);
				process.setNextsprIds(null);
			}
			process.setHeadId(report.getId());
			process.setEquipmentId(report.getEquipmentId());
			process.setLczt(report.getLczt());
			process.setType(type);
			process.setOpBy(StringUtil.getPlatformUid());
			process.setOpAt(Times.getTS());
			busEquipmentService.update(equipment);
			busEquipmentReportService.update(report);
			busEquipmentProcessService.insert(process);
			busEquipmentReportService.clearCache();
			return Result.success("system.success");
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}


	@At({"/delete","/delete/?"})
	@Ok("json")
	@RequiresPermissions("equipment.report.delete")
	@SLog(tag = "Delete", msg = "Delete:bus_equipment_report")
	public Object delete(String id,@Param("ids") String[] ids, HttpServletRequest req) {
		try {
			if(ids!=null&&ids.length>0){
				busEquipmentReportService.vDelete(ids);
			}else{
				busEquipmentReportService.vDelete(id);
			}
			busEquipmentReportService.clearCache();
			return Result.success("system.success");
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}

	@At({"/itemDelete","/itemDelete/?"})
	@Ok("json")
	@RequiresPermissions("equipment.report.delete")
	@SLog(tag = "Delete", msg = "Delete:bus_equipment_report")
	public Object itemDelete(String id,@Param("ids") String[] ids, HttpServletRequest req) {
		try {
			if(ids!=null&&ids.length>0){
				busEquipmentReportItemService.delete(ids);
			}else{
				busEquipmentReportItemService.delete(id);
			}
			busEquipmentReportService.clearCache();
			return Result.success("system.success");
		} catch (Exception e) {
			return Result.error("system.error");
		}
	}


	@At("/createWord/?")
	@Ok("json")
	@SLog(tag = "生成设备确认表", msg = "确认表id:${args[0]}")
	public Object createWord(String id) {
		try {
			BusEquipmentReport report = busEquipmentReportService.fetchLinks(busEquipmentReportService.fetch(id),"reportItems",Cnd.NEW().asc("sort"));
			BusEquipmentInspection inspection = busEquipmentInspectionService.fetch(report.getInspectionId());
			BusEquipment equipment = busEquipmentService.fetch(report.getEquipmentId());
			List<BusEquipmentProcess> listProcess = busEquipmentProcessService.listEntity(Sqls.create("select * from  bus_equipment_process es where " +
					" equipmentId='"+report.getEquipmentId()+"' and headId='"+report.getId()+"' and type='"+type+"' and lczt>1 and delFlag=0 order by opAt desc"));
			//获取协议书模板路径
			BusinessFileInfo agreementTemplate = businessFileInfoService.fetch(Cnd.where("delFlag", "=", "0").and("infoType","=","equipment.report"));
			if(agreementTemplate==null){
				return Result.error("请上传设备确认表模板后再生成！");
			}
			String uploadPath = this.getUploadPathConfig();
			String demoAgreement = uploadPath+agreementTemplate.getFilePath();

			//获取生成的确认表路径
			String date= DateUtil.format(new Date(), "yyyy")+"/"+DateUtil.format(new Date(), "MM")+"/"+DateUtil.format(new Date(), "dd");
			String fileName = report.getId();
			String newAgreementPath = "/equipment/report/" + date + "/" + fileName+".docx";
			String newAgreement = uploadPath+newAgreementPath;//确认表路径

			BusinessFileInfo oldReport = businessFileInfoService.fetch(Cnd.where("delFlag", "=", "0").and("fileName", "=", fileName).and("infoType","=","equipment.report"+fileName));

			Trans.exec(Connection.TRANSACTION_SERIALIZABLE, new Atom() {
				public void run() {
					if(oldReport!=null){
						//先删除历史的文件
						File old_report_file = new File(uploadPath+oldReport.getFilePath());
						old_report_file.delete();
						if (old_report_file.exists()) {
							if (old_report_file.isFile()) {//boolean isFile():测试此抽象路径名表示的文件是否是一个标准文件。
								old_report_file.delete();
							}
						}
						businessFileInfoService.delete(oldReport.getId());
					}
				}
			});
			Map<String, String> map = new HashMap<String, String>();
			map.put("PE_name", equipment.getName());
			map.put("PE_code", equipment.getCode());
			if(inspection!=null) {
				map.put("PE_measurementUnit", inspection.getMeasurementUnit());
			}
			map.put("PE_reportCode", report.getReportCode());
			map.put("PE_calculateDate", DateUtil.StringFormat(report.getCalculateDate(),"yyyy年MM月dd日"));
			map.put("PE_calculateAccord", report.getCalculateAccord());
			map.put("PE_ability", getNames(report.getAbility(),"","ability"));
			map.put("PE_accord",getNames(report.getAccord(),"，","accord"));

			for (int i = 0; i < listProcess.size()&&i<2; i++) {
				BusEquipmentProcess p = listProcess.get(0);
				Sys_user slrUser = sysUserService.fetch(p.getOpBy());
				String fileId = slrUser.getFileId();
				if (!StringUtils.isEmpty(fileId)) {
					BusinessFileInfo signatureImage = businessFileInfoService.fetch(fileId);
					map.put("PE_qm"+(i+1), uploadPath + signatureImage.getFilePath());
				}
				map.put("PE_rq"+(i+1), DateUtil.getDate(p.getOpAt(),"yyyy年MM月dd日"));
			}
			DocUtils.FileEReport(demoAgreement,newAgreement,map,report.getReportItems());

			BusinessFileInfo file = new BusinessFileInfo();
			file.setInfoName(fileName);
			file.setInfoVersion(date);
			file.setInfoType("equipment.report"+fileName);
			file.setRemark("");
			file.setOperatorName(StringUtil.getPlatformUsername());
			file.setFileType(".docx");
			file.setDisabled(false);
			file.setFilePath(newAgreementPath);
			file.setFileName(fileName);
			file.setFileBeforeName( fileName+".docx");
			file.setFileUrl(newAgreement);
			businessFileInfoService.insert(file);
			return Result.success("生成成功！").addData(newAgreement);
		} catch (Exception e) {
			e.printStackTrace();
			return Result.error("system.error");
		}
	}
	public String getNames(String ids,String spl,String type){
		String names ="";
		Map map= sysDictService.getCodeMap(type);
		if(!StringUtils.isEmpty(ids)){
			String[] id = ids.split(",");
			for(int i = 0 ; i <id.length ;i++){
				names += map.get(id[i]);
				if(i<(id.length-1)){
					names+=spl;
				}
			}
		}
		return names;
	}
	private String getUploadPathConfig() throws Exception {
		String uploadPath;
		//系统没开启配置,上传到项目路径
		if ("false".equals(Globals.MyConfig.getOrDefault("IsConfigUploadPath", "false"))){
			uploadPath= UploadController.class.getClassLoader().getResource("").getPath()+"upload";
		}else if (
				("true".equals(Globals.MyConfig.getOrDefault("IsConfigUploadPath", "false")))&&(Globals.MyConfig.getOrDefault("ConfigUploadPath", null)!=null)
		){
			uploadPath=Globals.MyConfig.get("ConfigUploadPath").toString();
		}else {
			throw new Exception("文件上传路径配置有误");
		}
		return uploadPath;
	}


	@Aop(TransAop.READ_COMMITTED)
	@At()
	@Ok("json")
	@SLog(tag = "设备确认上传模板", msg = "fileId:${args[0]}")
	public Object upWord(@Param("fileId") String fileId) {
		try {
			businessFileInfoService.execute(Sqls.create(" update bus_file_info set delFlag=1 where infoType='equipment.report' "));
			BusinessFileInfo reportheaderTemplate = businessFileInfoService.fetch(fileId);
			reportheaderTemplate.setInfoType("equipment.report");
			reportheaderTemplate.setDelFlag(false);
			businessFileInfoService.update(reportheaderTemplate);
			return Result.success();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return Result.error();
		}
	}
}
